﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Semantics.Base;

namespace Semantics.Parse
{
    public class SemanticNodesAmbiguitiesResolve
    {
        public LangNode CurrentLangNode { get { return this.LangNodeTraverser.Current; } }

        /// <summary>
        /// Key: SemanticNode.SN
        /// Value: SemanticNode
        /// </summary>
        SortedList<int, SemanticNode> CandidateSemanticNodesIndex = new SortedList<int, SemanticNode>();

        LangNodeTraverser LangNodeTraverser;
        public SemanticNodesAmbiguitiesResolve(LangNode langnode)
        {
            LangNodeTraverser = new LangNodeTraverser(langnode);
            for(int i=langnode.SemanticNodes.Count-1;i>=0;i--)
                EnrollSemanticNode(langnode.SemanticNodes[i]);
        }

        public bool MoveNext()
        {
            return this.LangNodeTraverser.MoveNext();
        }
#region LangNodeSemanticNodeAmbiguity
        //public class LangNodeSemanticNodeAmbiguity
        //{
        //    public LangNodeSemanticNodeAmbiguity(LangNode langnode)
        //    {
        //        this.LangNode=langnode;
        //    }
        //    public LangNode LangNode;
        //    public List<SemanticNode> AmbiguousSemanticNodes=new List<SemanticNode>();
        //}
        //SortedList<int, LangNodeSemanticNodeAmbiguity> Ambiguities = new SortedList<int, LangNodeSemanticNodeAmbiguity>();
        //LangNodeSemanticNodeAmbiguity GetLangNodeAmbiguity(LangNode langnode)
        //{
        //    LangNodeSemanticNodeAmbiguity ambiguity = null;
        //    if(this.Ambiguities.ContainsKey(semanticnode.LanguageNode.SN))
        //        ambiguity = this.Ambiguities[semanticnode.LanguageNode.SN];
        //    else
        //    {
        //        ambiguity=new LangNodeSemanticNodeAmbiguity(semanticnode.LanguageNode);
        //        this.Ambiguities.Add(ambiguity.LangNode.SN, ambiguity);
        //    }
        //    return ambiguity;
        //}
#endregion
        /// <summary>
        /// After disambiguition, ambiguous SemanticNode should be dismissed
        /// </summary>
        /// <param name="langnode"></param>
        /// <returns>The remain SemanticNode. If only one, it is unambiguous.</returns>
        public List<SemanticNode> GetRemainSemanticNodeOfLangNode(LangNode langnode)
        {
            List<SemanticNode> semanticnodes=new List<SemanticNode>();
            for (int i = langnode.SemanticNodes.Count - 1; i >= 0; i--)
            {//not all semanticnode of a langnode can be candidate, since some of them may be defeated for some reason
                if (this.CandidateSemanticNodesIndex.ContainsKey(langnode.SemanticNodes[i].SN))
                    semanticnodes.Add(langnode.SemanticNodes[i]);//Only the SemanticNodes within CandidateSemanticNodesIndex is valide candidate
            }
            return semanticnodes;
        }
        public void EnrollSemanticNode(SemanticNode semanticnode)
        {
            if (!this.CandidateSemanticNodesIndex.ContainsKey(semanticnode.SN))
                this.CandidateSemanticNodesIndex.Add(semanticnode.SN, semanticnode);
            for (int i = semanticnode.Children.Count - 1; i >= 0; i--)
                this.EnrollSemanticNode(semanticnode.Children[i].Child);
        }

        /// <summary>
        /// 递归删除一个SemanticNode及其上级节点
        /// </summary>
        /// <param name="semanticnode"></param>
        public void DismissSemanticNode(SemanticNode semanticnode, SemanticNode winner)
        {
            this.CandidateSemanticNodesIndex.Remove(semanticnode.SN);
            semanticnode.DefeatedBy = winner;
            for (int i = semanticnode.Parents.Count - 1; i >= 0; i--)
            {
                SemanticNode parent = semanticnode.Parents[i].Parent;
                if (this.CandidateSemanticNodesIndex.ContainsKey(parent.SN))
                {
                    DismissSemanticNode(parent, winner);
                    parent.DefeatedReason = SemanticNode.DefeatedReasonType.ChildDefeated;
                }
            }
        }
        public void Apply(SemanticNode semanticnode)
        {
            for (int i = semanticnode.LanguageNode.SemanticNodes.Count - 1; i >= 0; i--)
            {
                SemanticNode candidate = semanticnode.LanguageNode.SemanticNodes[i];
                if (candidate == semanticnode)
                    continue;
                if (this.CandidateSemanticNodesIndex.ContainsKey(candidate.SN))
                {
                    if (candidate.Pattern == null)
                        candidate.DefeatedReason = SemanticNode.DefeatedReasonType.WordSenseDisambugate;
                    else
                        candidate.DefeatedReason = SemanticNode.DefeatedReasonType.Restrain;
                    DismissSemanticNode(candidate, semanticnode);
                }
            }
        }

        public void Reset()
        {
            this.LangNodeTraverser.Reset();
        }
        public List<SemanticNode> GetCandidatesSemanticNodes()
        {
            List<SemanticNode> candidates=new List<SemanticNode>();
            while (true)
            {
                for (int i = this.CurrentLangNode.SemanticNodes.Count - 1; i >= 0; i--)
                {
                    if (this.CandidateSemanticNodesIndex.ContainsKey(this.CurrentLangNode.SemanticNodes[i].SN))
                        candidates.Add(this.CurrentLangNode.SemanticNodes[i]);
                }
                if (candidates.Count == 0)
                    this.MoveNext();
                else
                    return candidates;
            }
        }
    }
}
